//
//  YZInAppPurchaseViewCtl.m
//  raceme
//
//  Created by mac on 2021/9/11.
//

#import "YZInAppPurchaseViewCtl.h"
#import <StoreKit/StoreKit.h>
#import "YZChargeDefaultsModel.h"


@interface YZInAppPurchaseViewCtl ()<SKPaymentTransactionObserver,SKProductsRequestDelegate>
@property(nonatomic,strong)NSString * appleUrl;
@property(nonatomic,strong)UILabel * payLab;
@property(nonatomic,strong)NSString * orderId;
@property(nonatomic,strong)NSString * currentProducId;
@property(nonatomic,strong)NSString * receipt;
@end

@implementation YZInAppPurchaseViewCtl

- (void)viewDidLoad {
    [super viewDidLoad];
    
    
    _appleUrl = @"https://buy.itunes.apple.com/verifyReceipt";
    NSString * vFromSelfServer = [self getAppleInfoFromSelfServer];
    NSString * vCurrIPA = @"当前安装包的版本号";
    if([vFromSelfServer isEqualToString:vCurrIPA]){
//      当前安装包的版本号和服务端返回的版本号一致,就将appleUrl的值改为沙盒验证,因为这种情况下表示app正在被审核中
        _appleUrl = @"https://sandbox.itunes.apple.com/verifyReceipt";
    }

    
//    添加交易监听
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    
    [self.view addSubview:self.payLab];

    
}
#pragma mark --------- self server request

/**
 * 用接口从自己服务器获取版本号
 *    1.发布更新提交审核时候,从itunes中选项改为手动发布
 *    2.让服务端将getAppleInfoFromSelfServer这个接口返回的版本号和发布给苹果审核的版本号一致
 *    3.等待苹果审核通过,先让服务端将getAppleInfoFromSelfServer的值改一下成无限大(这里只要不等于线上所有用户的版本号,也不等于当前已审核通过的版本号即可)
 *    4.itunes手动发布已审核通过的ipa包
 */
-(NSString *)getAppleInfoFromSelfServer {
    
    return @"自己服务器返回的一个版本号";
}

/**
 * 创建订单
 */
-(NSString *)creatOrderFromSelfServer:(NSString *)priceID {
    return @"服务端根据priceID返回的一个orderId";
}


-(UILabel *)payLab {
    if (_payLab == nil) {
        _payLab = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
        _payLab.text = @"Pay request";
        _payLab.textAlignment = NSTextAlignmentCenter;
        _payLab.font = [UIFont systemFontOfSize:16];
        _payLab.layer.cornerRadius = 3;
        _payLab.layer.masksToBounds = YES;
        _payLab.layer.borderWidth = 0.5;
        _payLab.layer.borderColor = [UIColor blueColor].CGColor;
        _payLab.textColor = [UIColor blueColor];
        _payLab.userInteractionEnabled = YES;
        UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] init];
        [[tap rac_gestureSignal] subscribeNext:^(__kindof UIGestureRecognizer * _Nullable x) {
//            自己在苹果商城申请的类别的ID列表为
           //  bundleid+xxx 就是你添加内购条目设置的产品ID
//            zydj.product.pay_6  6元4.2豆
//            zydj.product.pay_40 40元28豆
//            zydj.product.pay_60 60元48豆
//            假设选中了6元4.2豆则通过zydj_product_pay_6在自己服务端创建订单
            
            self.currentProducId = @"zydj.product.pay_6";
            
            NSString * orderId =  [self creatOrderFromSelfServer:self.currentProducId];
      
            self.orderId = orderId;
            
            [self startInAppPay];
            
        }];
        [_payLab addGestureRecognizer:tap];
    }
    return _payLab;
}

#pragma mark --------- about apple
/**
 * Apple Operation
 */
-(void)startInAppPay {
    //判断是否允许内购
    if ([SKPaymentQueue canMakePayments]) {
        NSLog(@"用户允许内购");
        //bundleid+xxx 就是你添加内购条目设置的产品ID
        NSArray *product = [[NSArray alloc] initWithObjects:@"zydj.product.pay_6",@"zydj.product.pay_40",@"tv.zydj.app_pay_6",@"zydj.product.pay_60", nil];
        NSSet *nsset = [NSSet setWithArray:product];
        
        //初始化请求
        SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
        request.delegate = self;
        
        //开始请求
        [request start];
        
//        注意,这里请求成功之后,会走到)productsRequest:
        
        
    }else{
       //  NSLog(@"用户不允许内购");
//        [ToastUtils showMessage:@"当前设备不允许内购" duration:1 position:Toast_Point_Center];
    }
}


//接收到产品的返回信息，然后用返回的商品信息进行发起购买请求
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response NS_AVAILABLE_IOS(3_0)
{
    NSArray *product = response.products;

    //如果苹果服务器没有产品,那就return
    if([product count] == 0){
        NSLog(@"没有该商品");
        return;
    }
    
    SKProduct *requestProduct = nil;

    NSString * currentProducId = self.currentProducId;
    
    for (SKProduct *pro in product) {
        
        NSLog(@"%@", [pro description]);
        NSLog(@"%@", [pro localizedTitle]);
        NSLog(@"%@", [pro localizedDescription]);
        NSLog(@"%@", [pro price]);
        NSLog(@"%@", [pro productIdentifier]);
        
        //如果后台消费条目的ID与我这里需要请求的一样（用于确保订单的正确性）
        if([pro.productIdentifier isEqualToString:currentProducId]){
//            到这一步就说明商品存在,开始发送购买请求
            requestProduct = pro;
            SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:requestProduct];
            payment.applicationUsername = self.orderId;//可以是userId，也可以是订单id，跟你自己需要而定
            [[SKPaymentQueue defaultQueue] addPayment:payment];
            // 如果请求成功就会弹出输入密码等页面,输入完密码之后会出现一个支付成功的弹窗,点击了弹窗之后会进入paymentQueue:方法中
        }
    }
}

/**
 * 有两种方式会进入这个方法回调中
 * 方式1:正常流程,用户输入密码,支付成功之后,点击了系统弹出的支付成功弹窗,就会进入这个方法回调中
 * 方式2:异常流程,当用户输入完密码之后,苹果实际扣款成功,用户手机异常退出(闪退或者直接杀掉APP,断电等情况异常离开app),下次打开APP进入到充值页面之后,viewDidLoad中添加了支付回调监听之后,也会进这个方法回调中
 *
 */
- (void)paymentQueue:(nonnull SKPaymentQueue *)queue updatedTransactions:(nonnull NSArray<SKPaymentTransaction *> *)transactions {
    
    dispatch_async(dispatch_get_main_queue(), ^{
        for(SKPaymentTransaction *tran in transactions){
            switch (tran.transactionState) {
                case SKPaymentTransactionStatePurchased:{
                    NSLog(@"交易完成");
//                    接下来的流程
                    [self completeTransaction:tran];
                }
                    break;
                case SKPaymentTransactionStatePurchasing:
                    
                    NSLog(@"商品添加进列表");
                    break;
                case SKPaymentTransactionStateRestored:
                    
                    NSLog(@"已经购买过商品");
                    //[[SKPaymentQueue defaultQueue] finishTransaction:tran]; 消耗型商品不用写
                    break;
                case SKPaymentTransactionStateFailed:{
                    //这里说明支付失败了啊.密码输入错误或者没扣款成功,那就finish掉这笔交易
                    [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                    NSLog(@"交易失败");
                }
                    break;
                default:
                    break;
            }
        }

    });

}



//交易结束,当交易结束后还要去appstore上验证支付信息是否都正确,只有所有都正确后,我们就可以给用户方法我们的虚拟物品了。
- (void)completeTransaction:(SKPaymentTransaction *)transaction
{

    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.orderId.length != 0) {
//            这里需要展示一个加载框,展示出来之后要禁止掉用户的点击其他view区域的操作,包括左滑返回也给禁止掉
//            [MBProgressHUD showLoadHUD:@"加载中..." toView:self.view];
        }
        // appStoreReceiptURL iOS7.0增加的，购买交易完成后，会将凭据存放在该地址
        // 验证凭据，获取到苹果返回的交易凭据
        NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
        // 从沙盒中获取到购买凭据
        NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
        //发送POST请求，对购买凭据进行验证
        
        NSLog(@"before = %@",receiptURL);
        
        NSURL *url = [NSURL URLWithString:_appleUrl];
        
        NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15.0f];
        urlRequest.HTTPMethod = @"POST";
        NSString *encodeStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
        _receipt = encodeStr;
        
        //防止异常退出做的操作
    if (self.orderId.length != 0) {
        YZChargeDefaultsModel * model = [[YZChargeDefaultsModel alloc] init];
        model.orderId = self.orderId;
        model.receipt = encodeStr;
        NSData * data = [NSKeyedArchiver archivedDataWithRootObject:model];
        SAVEDEFAULTS(data, transaction.transactionIdentifier);
//        这里存到userdefaults
    }
        NSString *payload = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodeStr];
        NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
        urlRequest.HTTPBody = payloadData;
        
        NSURLSessionTask *task =   [[NSURLSession sharedSession] dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//            [MBProgressHUD hideHUD];
            if (data == nil) {
                NSLog(@"验证失败");
                return;
            }
            
            NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
            NSLog(@"请求成功后的数据:%@",dic);
            //这里可以通过判断 state == 0 验证凭据成功，然后进入自己服务器二次验证，,也可以直接进行服务器逻辑的判断。
            //本地服务器验证成功之后别忘了 [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
            NSString *productId = transaction.payment.productIdentifier;
            NSString *applicationUsername = transaction.payment.applicationUsername;
            
            NSLog(@"applicationUsername++++%@",applicationUsername);
            NSLog(@"payment.productIdentifier++++%@",productId);

            
            if (dic != nil) {
                
                NSLog(@"order id == null");
                
                NSArray * array = dic[@"receipt"][@"in_app"];
                if (array.count <= 0) {
                    return;
                }
                self.orderId = applicationUsername;
                //服务器二次验证
                NSLog(@"%@",transaction);
                
                for (int i = 0; i < array.count; i ++) {
                    NSDictionary * dic = array[i];
                    NSString * transaction_id = dic[@"transaction_id"];
                    if ([transaction.transactionIdentifier isEqualToString:transaction_id]) {
                        if (self.orderId.length != 0) {
                                [self vertifyApplePayRequestWith:transaction receipt:self.receipt transactionOrderId:self.orderId];
                        }else {
                            NSData * data = GETDEFAULTS(transaction.transactionIdentifier);
                            YZChargeDefaultsModel * model = [NSKeyedUnarchiver unarchiveObjectWithData:data];
                            if (model.orderId.length != 0 && model.receipt.length != 0) {
                                [self vertifyApplePayRequestWith:transaction receipt:model.receipt transactionOrderId:model.orderId];
                            }else {
                                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                            }
                        }
                    }
                }

            }
        }];
        [task resume];
    });
}


-(void)vertifyApplePayRequestWith:(SKPaymentTransaction *)transaction receipt:(NSString *)receipt transactionOrderId:(NSString *)orderId{
//    NSMutableDictionary * dic = [NSMutableDictionary dictionary];
//    [dic setObject:receipt forKey:@"receipt_data"];
//    NSString * alltransId = [NSString stringWithFormat:@"%@%@",YZ_Transaction_ID,transaction.transactionIdentifier];
//    NSString * needtransID = [alltransId md5String];
//    [dic setObject:orderPhpId forKey:@"orderNum"];
//    [dic setObject:needtransID forKey:@"transactionID"];
    
//    根据一些参数,向服务端请求验证当前订单是否支付
//    transaction.transactionIdentifier //唯一的
//    receipt 一般这个数据很长很长很长, md5一下,传输方便
//    orderId
    
//    服务端的一些处理
//    先判断这个transaction.transactionIdentifier对应的订单是否支付成功且发放了虚拟物品 如果是就直接返回一个状态比如状态1
//    客户端在状态1的处理就是直接finish掉这笔交易
//    如果发送虚拟物品的记录中没有这条记录,那么先通过transaction.transactionIdentifier向apple再次验证一下是否支付成功,如果支付成功,那么就发放虚拟物品给用户,并在当前接口中返回状态2
//    客户端在状态2的处理就是 finish掉这笔交易,并删除本地的transactionIdentifier对应的YZChargeDefaultsModel,并记录一下transactionIdentifierd对应的交易已经成功,为了应对状态1的情况
//    如果发送虚拟物品的记录中没有这条记录,那么先通过transaction.transactionIdentifier向apple再次验证一下是否支付成功,如果支付失败,那么返回状态3给客户端,然后什么都不用记录
//    客户端在状态3的处理就是直接finish掉这笔交易,因为服务端验证获取到的信息是用户支付的资金没有到账
    
    NSInteger status = 0;
        if(status == 1){
            [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
        }else if (status == 2){
            [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
        }else if(status == 3) {
            [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
        }
            if (self.orderId.length != 0) {
//                [ToastUtils showMessage:responseObjc[@"msg"] duration:1 position:Toast_Point_Center];
                self.orderId = @"";
                [[NSUserDefaults standardUserDefaults] removeObjectForKey:transaction.transactionIdentifier];
            }

        
}


#pragma mark - SKRequestDelegate
//请求失败
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
    NSLog(@"error:%@", error);
}

//请求结束
- (void)requestDidFinish:(SKRequest *)request
{
    NSLog(@"请求结束");
}


@end

